#include <iostream>
#include <string>
#include <vector>

#include <unistd.h>
#include <pthread.h>

#include "lockguard.hpp"

#define NUM 4

int tickets = 1000;

// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

class thread_data
{
public:
    thread_data(int number, pthread_mutex_t* mutex)
    {
        _name = "thread_" + std::to_string(number);
        _mutex = mutex;
    }

    std::string _name;
    pthread_mutex_t* _mutex;
};

void* get_ticket(void* args)
{
    thread_data* td = static_cast<thread_data*>(args);
    for (int i = 0; true; ++i)
    {
        {
            LockGuard lg(td->_mutex);
            if (tickets > 0)
            {
                usleep(1000);
                std::cout << td->_name << " sells tickets " << tickets << std::endl;
                --tickets;
            }
            else
                break;
        }
        usleep(10);

        // pthread_mutex_lock(td->_mutex);
        // if (tickets > 0)
        // {
        //     usleep(1000);
        //     std::cout << td->_name << " sells tickets " << tickets << std::endl;
        //     --tickets;
        //     pthread_mutex_unlock(td->_mutex);
        // }
        // else
        // {
        //     pthread_mutex_unlock(td->_mutex);
        //     break;
        // }
        // usleep(13);
    }
    std::cout << td->_name << "is quit" << std::endl;
    delete td;
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);

    std::vector<pthread_t> tids;
    std::vector<thread_data*> tdatas;
    for (int i = 0; i < NUM; ++i)
    {
        thread_data* td = new thread_data(i, &mutex);
        tdatas.push_back(td);
        pthread_t tid;
        pthread_create(&tid, nullptr, get_ticket, tdatas[i]);
        tids.push_back(tid);
    }

    for (int i = 0; i < NUM; ++i)
    {
        pthread_join(tids[i], nullptr);
    }

    pthread_mutex_destroy(&mutex);

    return 0;
}